#include <stdio.h>
#include "echatimsdk.h"
#include <string.h>

#ifdef WINDOW_VISUAL_STUDIO
#include <windows.h>
#else
#include <dlfcn.h>
#endif

#ifdef WINDOW_VISUAL_STUDIO
    #define  DLL_HANDLE HMODULE
    #define  DLL_LOAD_DLL(PATH)  LoadLibrary(PATH)
    #define  DLL_ERROR
    #define  DLL_GET_METHOD(HANDLE, METHOD)  GetProcAddress(HANDLE, METHOD)
#else
    #define  DLL_HANDLE void*
    #define  DLL_LOAD_DLL(PATH)  dlopen(PATH, RTLD_NOW)
    #define  DLL_ERROR  printf("call dll failed: %s", dlerror())
    #define  DLL_GET_METHOD(HANDLE, METHOD)  dlsym(HANDLE, METHOD)
#endif

// sdk dll
pfunc_sdk_init sdkInit = NULL;
pfunc_sdk_set_api_listener sdkSetApiListener = NULL;
pfunc_sdk_invoke_api sdkInvokeApi = NULL;

// fileserver dll
pfunc_sdk_fileserver_instance sdkFileServerInstance = NULL;
pfunc_sdk_fileserver_init sdkFileServerInit = NULL;
pfunc_sdk_fileserver_set_upload_listener sdkFileServerSetUploadListener = NULL;
pfunc_sdk_fileserver_invoke_upload sdkFileServerInvokeUpload = NULL;
pfunc_sdk_fileserver_release sdkFileServerRelease = NULL;


int sdk_init_finished = 0;
int api_call_id = 1; // api 调用id, 实现方式可用时间戳, 或一个自增变量

void sdk_init_callback_handler(int ret, const char *err_msg){
    if(ret == 0){
        sdk_init_finished = 1;
    }
}

void sdk_listener_callback_handler(const char *method, int argc, const char *argv[]){
    if(strlen(method) > 0 && argc > 0){
        printf("sdk_listener_callback_handler: method = %s, argv[0]=%s", method, argv[0]);
    }
}

void sdk_api_callback_handler(unsigned long call_id, const char *api_method, const char *response){
    if(strlen(api_method) > 0 && strlen(response) > 0){
        printf("sdk_api_callback_handler: call_id = %lu, method = %s, argv[0]=%s", call_id, api_method, response);
    }
}

void sdk_fileserver_upload_callback_handler(unsigned long handle_id, const char *method, int argc, const char *argv[]){
    if(handle_id > 0 && strlen(method) > 0 && argc > 0){
        if(strcmp(method, "errorCallback") == 0){
            fprintf(stderr, "handle_id[0x%lx], errorCallback:%s, errMsg:%s \n", handle_id, argv[0], argv[1]);
        }
        else if(strcmp(method, "progressCallback") == 0){
            fprintf(stdout, "handle_id[0x%lx], progressCallback:%s \n", handle_id, argv[0]);
        }
        else if(strcmp(method, "uploadedCallback") == 0){
            fprintf(stdout, "handle_id[0x%lx], uploadedCallback:%s \n", handle_id, argv[0]);
        }
    }
}

void sdk_test_apis(){
    // 测试 'userGet'
    sdkInvokeApi(api_call_id++, "userGet", "{\"auid\":\"admin\"}");

    sdkInvokeApi(api_call_id++, "userUpdate", "{}");
    sdkInvokeApi(api_call_id++, "userList", "{}");
    sdkInvokeApi(api_call_id++, "userGet", "{}");
    sdkInvokeApi(api_call_id++, "userUpdateToken", "{}");
    sdkInvokeApi(api_call_id++, "userRefreshToken", "{}");
    sdkInvokeApi(api_call_id++, "historyListMessage", "{}");
    sdkInvokeApi(api_call_id++, "historyListSession", "{}");
    sdkInvokeApi(api_call_id++, "addFriend", "{}");
    sdkInvokeApi(api_call_id++, "delFriend", "{}");
    sdkInvokeApi(api_call_id++, "listFriends", "{}");
    sdkInvokeApi(api_call_id++, "getFriend", "{}");
    sdkInvokeApi(api_call_id++, "modifyBlacklistForbid", "{}");
    sdkInvokeApi(api_call_id++, "listBlackListForbid", "{}");
    sdkInvokeApi(api_call_id++, "modifyAlias", "{}");
    sdkInvokeApi(api_call_id++, "addRoom", "{}");
    sdkInvokeApi(api_call_id++, "updateRoom", "{}");
    sdkInvokeApi(api_call_id++, "listRoom", "{}");
    sdkInvokeApi(api_call_id++, "listRoomJoin", "{}");
    sdkInvokeApi(api_call_id++, "delRoom", "{}");
    sdkInvokeApi(api_call_id++, "getRoom", "{}");
    sdkInvokeApi(api_call_id++, "listRoomMember", "{}");
    sdkInvokeApi(api_call_id++, "addRoomMember", "{}");
    sdkInvokeApi(api_call_id++, "delRoomMember", "{}");
    sdkInvokeApi(api_call_id++, "userOnline", "{}");
}

void sdk_dll_task(const char *config){
    if(sdkInit == NULL || sdkSetApiListener == NULL || sdkInvokeApi == NULL){
        printf("dll method not found.");
        return;
    }

    sdkInit(config, sdk_init_callback_handler, sdk_listener_callback_handler);
    // 等待sdk初始完成.
    while (!sdk_init_finished){
        printf(".");
    }
    sdkSetApiListener(sdk_api_callback_handler);
    sdk_test_apis();
    // 获取上传实例
    HANDLE_ID_TYPE file_handle = sdkFileServerInstance();
    printf("sdkFileServerInstance finished, file_handle_id:0x%lx \n",file_handle);
    const char *UPLOAD_CONFIG = "{\"maxFileSize\":100,\"allowSuffix\":[\"jpeg\",\"zip\",\"mp3\"],\"type\":\"FILE\"}";
    // 初始化上传实例, 设置上传回调监听.
    sdkFileServerInit(file_handle, UPLOAD_CONFIG);
    sdkFileServerSetUploadListener(file_handle, sdk_fileserver_upload_callback_handler);
    // 文件上传
//    const char *FILE_PATH = "C:\\Users\\Administrator\\Desktop\\upload\\a.mp3";
    const char *FILE_PATH = "C:\\Users\\Administrator\\Desktop\\upload\\a.txt";
//    const char *FILE_PATH = "/tmp/a.txt";
    sdkFileServerInvokeUpload(file_handle, FILE_PATH, 0);

    sdkFileServerRelease(file_handle);

    printf("echatim sdk init ok.");
    while (1);
}






const char *SDK_DLL_PATH = "C:\\Users\\Administrator\\CLionProjects\\echatim-client-cpp-core\\cmake-build-debug\\libs\\echatimsdk.dll";
//const char *SDK_DLL_PATH = "/Users/kong/CLionProjects/echatim-client-cpp-core/cmake-build-debug/libs/libechatimsdk.dylib";
//const char *SDK_DLL_PATH = "这里填写echatim-client-cpp-core 编译出的动态库路径";

int main() {
    printf("准备加载 echatim sdk 动态库...");
    DLL_HANDLE handle = DLL_LOAD_DLL(SDK_DLL_PATH);
    if (!handle) {
        DLL_ERROR;
        printf("echatim sdk 动态库加载失败.");
        return -1;
    }
    printf("准备获取 echatim sdk 动态库中函数地址...");
    sdkInit = (pfunc_sdk_init) DLL_GET_METHOD(handle, "sdk_init");
    if(sdkInit == NULL){
        printf("get dll method sdk_init failed");
        return -1;
    }
    sdkSetApiListener = (pfunc_sdk_set_api_listener) DLL_GET_METHOD(handle, "sdk_set_api_listener");
    if(sdkSetApiListener == NULL){
        printf("get dll method sdk_set_api_listener failed");
        return -1;
    }
    sdkInvokeApi = (pfunc_sdk_invoke_api) DLL_GET_METHOD(handle, "sdk_invoke_api");
    if(sdkInvokeApi == NULL){
        printf("get dll method sdk_invoke_api failed");
        return -1;
    }

    // 文件服务器DLL
    sdkFileServerInstance = (pfunc_sdk_fileserver_instance) DLL_GET_METHOD(handle, "sdk_fileserver_instance");
    if(sdkFileServerInstance == NULL){
        printf("get dll method sdk_fileserver_instance failed");
        return -1;
    }
    sdkFileServerInit = (pfunc_sdk_fileserver_init) DLL_GET_METHOD(handle, "sdk_fileserver_init");
    if(sdkFileServerInit == NULL){
        printf("get dll method sdk_fileserver_init failed");
        return -1;
    }
    sdkFileServerSetUploadListener = (pfunc_sdk_fileserver_set_upload_listener) DLL_GET_METHOD(handle, "sdk_fileserver_set_upload_listener");
    if(sdkFileServerSetUploadListener == NULL){
        printf("get dll method sdk_fileserver_init failed");
        return -1;
    }
    sdkFileServerInvokeUpload = (pfunc_sdk_fileserver_invoke_upload) DLL_GET_METHOD(handle, "sdk_fileserver_invoke_upload");
    if(sdkFileServerInvokeUpload == NULL){
        printf("get dll method sdk_fileserver_invoke_upload failed");
        return -1;
    }
    sdkFileServerRelease = (pfunc_sdk_fileserver_release) DLL_GET_METHOD(handle, "sdk_fileserver_release");
    if(sdkFileServerRelease == NULL){
        printf("get dll method sdk_fileserver_release failed");
        return -1;
    }

//    const char *configJson = "{\"host\":\"api.echatim.cn\",\"httpPort\":58082,\"socketPort\":59092,\"key\":\"TSDKTEST00001\",\"secret\":\"\",\"apiTransport\":\"HTTP\",\"loginAuid\":\"admin\",\"loginToken\":\"admin\"}";
    const char *configJson = "{\"host\":\"api.echatim.cn\",\"httpPort\":58082,\"socketPort\":59092,\"key\":\"TSDKTEST00001\",\"secret\":\"\",\"apiTransport\":\"HTTP\",\"loginAuid\":\"admin\",\"loginToken\":\"admin\",\"fileServerConfig\":{\"use\":\"local\",\"client\":\"curl\",\"baseUrl\":\"http://api.echatim.cn:58082\",\"version\":\"v1\"}}";
//    const char *configJson = "{\"host\":\"api.echatim.cn\",\"httpPort\":58082,\"socketPort\":59092,\"key\":\"TSDKTEST00001\",\"secret\":\"\",\"apiTransport\":\"HTTP\",\"loginAuid\":\"admin\",\"loginToken\":\"admin\",\"fileServerConfig\":{\"use\":\"local\",\"client\":\"curl\",\"baseUrl\":\"http://localhost:8082\",\"version\":\"v1\"}}";
    sdk_dll_task(configJson);

}